package nbcp.service

import nbcp.db.CacheKey

import org.springframework.stereotype.Service
import nbcp.base.comm.JsonMap
import nbcp.base.comm.StringMap
import nbcp.base.extend.getStringValue
import nbcp.db.*

@Service("request")
class ReqeustCacheService : IDataCache4Sql {
    companion object {
        private var db_all = mutableMapOf<Long, StringMap>()
        var db_local = ThreadLocal.withInitial {
            var ret = StringMap();
            db_all.put(Thread.currentThread().id, ret);
            return@withInitial ret;
        }
        val db: StringMap
            get() = db_local.get();
    }

    override fun isEnable(): Boolean {
        return false;
    }

    override fun clear(tableName: String) {
        //tableName == 0 表示清理当前线程 。
        if (tableName.isEmpty()) {
            db_all.remove(Thread.currentThread().id);
            db.clear();
            return;
        }

        var set = hashSetOf<String>()
        set.add("uk*-${tableName}-*")
        set.add("rk*-${tableName}-*")
        set.add("urk*-${tableName}-*")
        set.add("sql*-${tableName}-*")
        brokeCache(tableName, set)
    }

    override fun getCacheSeconds(tableName: String?): Int {
        return 0;
    }

    override fun getCacheJson(cacheKey: CacheKey): String {
        if( isEnable() == false) return "";
        return db.getStringValue(cacheKey.getExpression());
    }

    override fun setCacheJson(cacheKey: CacheKey, cacheJson: String) {
        if( isEnable() == false) return;
        db.put(cacheKey.getExpression(), cacheJson)
    }

    override fun brokeCache(tableName: String, keys: Set<String>) {
        if( isEnable() == false) return;
        //所有线程的相关数据都清除。
        if (tableName.isEmpty()) return;
        if (keys.isEmpty()) return;

        db_all.values.forEach { db ->
            db.keys.forEach { key ->
                if (isMatched(key, keys)) {
                    db.remove(key);
                }
            }
        }
    }

    private fun isMatched(key: String, keys_pattern: Set<String>): Boolean {
        keys_pattern.forEach { kp ->
            if (isMatched(key, kp)) return true;
        }
        return false;
    }

    private fun isMatched(key: String, key_pattern: String): Boolean {
        //key: sql-${tables}-${md5}
        //key_pattern: sql*-{abc}-*
        var preIndex = 0;
        key_pattern.split("*").filter { it.isNotEmpty() }.forEachIndexed { index, find ->
            preIndex = key.indexOf(find, preIndex);
            if (index == 0 && key_pattern.first() != '*') {
                if (preIndex != 0) return false;
            }
            if (preIndex < 0) return false;
        }

        return true;
    }
}
